package com.ds.infrastructure.hyperspace.container.internal.util;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http.*;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;

import javax.net.ssl.SSLException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;

/**
 * @author yaozh
 */
@Slf4j
public class HttpRequestUtil {
    private HttpRequestUtil() {

    }

    public static DefaultFullHttpRequest createFullHttpRequest(URI uri,
                                                               HttpVersion httpVersion,
                                                               HttpMethod httpMethod,
                                                               Map<CharSequence, Object> headers) {
        return createFullHttpRequest(uri, httpVersion, httpMethod, headers, null, null);
    }

    public static DefaultFullHttpRequest createFullHttpRequest(URI uri,
                                                               HttpVersion httpVersion,
                                                               HttpMethod httpMethod,
                                                               Map<CharSequence, Object> headers,
                                                               String body, String bodyEncoding) {
        DefaultFullHttpRequest request;
        if (StringUtil.isNullOrEmpty(body)) {
            request = new DefaultFullHttpRequest(httpVersion, httpMethod, uri.getRawPath());
        } else {
            request = new DefaultFullHttpRequest(httpVersion, httpMethod, uri.getRawPath()
                    , Unpooled.wrappedBuffer(getBytes(body, bodyEncoding)));
            request.headers().set(HttpHeaderNames.CONTENT_LENGTH, request.content().readableBytes());
        }
        addHeader(uri, headers, request);
        return request;

    }

    public static DefaultFullHttpRequest createFullHttpRequest(URI uri,
                                                               HttpVersion httpVersion,
                                                               HttpMethod httpMethod,
                                                               Map<CharSequence, Object> headers, ByteBuf body) {
        DefaultFullHttpRequest request;
        if (body == null) {
            request = new DefaultFullHttpRequest(httpVersion, httpMethod, uri.getRawPath());
        } else {
            request = new DefaultFullHttpRequest(httpVersion, httpMethod, uri.getRawPath(), body);
            request.headers().set(HttpHeaderNames.CONTENT_LENGTH, request.content().readableBytes());
        }
        addHeader(uri, headers, request);
        return request;

    }

    private static void addHeader(URI uri, Map<CharSequence, Object> headers, DefaultFullHttpRequest request) {
        request.headers().set(HttpHeaderNames.HOST, uri.getHost());
        if (headers != null) {
            for (Map.Entry<CharSequence, Object> header : headers.entrySet()) {
                request.headers().set(header.getKey(), header.getValue());
            }
        }
    }

    private static byte[] getBytes(String content, String charsetName) {
        try {
            return content.getBytes(charsetName);
        } catch (UnsupportedEncodingException e) {
            throw new IllegalStateException(e);
        }
    }

    /**
     * Configure SSL context if necessary.
     *
     * @param scheme
     * @return
     * @throws SSLException
     */
    public static SslContext getSslContext(String scheme) {
        if (HttpScheme.HTTP.toString().equalsIgnoreCase(scheme)) {
            return null;
        }
        // 不验证SERVER
        try {
            return SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();
        } catch (SSLException e) {
            log.error("SSLException !", e);
            throw new IllegalStateException(e);
        }
    }

    /**
     * create uri
     *
     * @param url
     * @return
     */
    public static  URI createUri(String url) {
        try {
            return new URI(url);
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * http port
     * @param uri
     * @return
     */
    public static int getPort(URI uri) {
        int port = uri.getPort();
        if (port == -1) {
            if (HttpScheme.HTTP.toString().equalsIgnoreCase(uri.getScheme())) {
                return HttpScheme.HTTP.port();
            } else if (HttpScheme.HTTPS.toString().equalsIgnoreCase(uri.getScheme())) {
                return HttpScheme.HTTPS.port();
            }
        }
        return port;
    }
}
